package com.master.service;

import com.master.dao.MiaoshaUserDao;
import com.master.domain.MiaoshaUser;
import com.master.redis.MiaoshaUserKey;
import com.master.redis.RedisServer;
import com.master.util.CodeMsg;
import com.master.util.MD5Util;
import com.master.util.UUIDUtil;
import com.master.vo.LoginVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;

@Service
public class MiaoshaUserService {

    public  static final String COOK1_NAME_TOKEN = "token";

    @Autowired
    MiaoshaUserDao miaoshaUserDao;

    @Autowired
    RedisServer redisService;

    public MiaoshaUser getByNameExist(String name){
        return miaoshaUserDao.getByName(name);
    }

    //登录功能
    public CodeMsg login(LoginVo loginVo, HttpServletResponse response){
        if(loginVo == null){
            return CodeMsg.SERVER_ERROR;
        }
        //前端经过第一次加密之后的密码
        String formPass = loginVo.getPassword();
        String mobile = loginVo.getMobile();
        //判断手机号是否存在
        //这块登录是先从缓存中查询User信息,查询不到再从数据库中查询
        MiaoshaUser user = getByName(mobile);
        if(user == null){
            //如果通过手机号查询不到用户,返回错误
            return CodeMsg.MOBILE_NOT_EXIST;
        }
        //验证密码
        String dbPass = user.getPassword();//获取数据库中的密码
        String dbSalt = user.getSalt();
        //将前端传入的密码进行第二次MD5加密之后与数据库中密码对比
        String calcPass = MD5Util.formPassToDBPass(formPass,dbSalt);
        if(!dbPass.equals(calcPass)){
            return CodeMsg.PASSWORD_ERROR;
        }
        String token = UUIDUtil.uuid();
        addCookie(response,user,token);
        return CodeMsg.SUCCESS;
    }

    private void addCookie(HttpServletResponse response,MiaoshaUser user,String token){
        //将用户信息序列化之后保存在Redis中
        //这块如果也起到了活跃session的功能,向浏览器重新发送Cookie的同时
        //重新发送Cookie相当于重置Cookie有效期,并且向redis中又重新写入key的有效期,也相当于重置redis中session的有效期
        redisService.set(MiaoshaUserKey.token,token,user);
        Cookie cookie = new Cookie(COOK1_NAME_TOKEN,token);
        //设置cookie有效期为两天
        cookie.setMaxAge(MiaoshaUserKey.token.expireSeconds());
        cookie.setPath("/");
        response.addCookie(cookie);
    }



    //从Redis缓存中获取用户信息
    public MiaoshaUser getByToken(String token,HttpServletResponse response){
        if(StringUtils.isEmpty(token)){
            return null;
        }
        MiaoshaUser user =  redisService.get(MiaoshaUserKey.token,token,MiaoshaUser.class);
        //延长有效期
        //向缓存中生成新的值,重新生成一个Cookie,达到延长有效期的目的
        if(user != null) {
            addCookie(response, user,token);
        }
        return user;
    }

    //对象缓存
    public MiaoshaUser getByName(String name){
        //取缓存
        //对象缓存只要不发生变化是永久有效的
       MiaoshaUser user =  redisService.get(MiaoshaUserKey.getByName,""+name,MiaoshaUser.class);
       if(user != null){
           return user;
       }
       //如果缓存中没有,则查询数据库
        user = miaoshaUserDao.getByName(name);
       if(user != null){
           //回填到缓存中
           redisService.set(MiaoshaUserKey.getByName,""+name,user);
       }
       return user;
    }

    //更新用户的信息
    //这块在更新信息的时候要保证缓存和数据库的一致性
    //是先更新缓存还是先更新数据库
    public boolean updatePassword(String name,String passwordNew,String token){
        //先从缓存中取对象
        MiaoshaUser user = getByName(name);
        if(user == null){
            return false;
        }
        //更新数据库
        MiaoshaUser toBeUpdate = new MiaoshaUser();
        toBeUpdate.setName(name);
        toBeUpdate.setPassword(MD5Util.formPassToDBPass(passwordNew,user.getSalt()));
        //更新数据库中的信息
        miaoshaUserDao.update(toBeUpdate);

        //处理缓存
        //关于token和name来获取对象的缓存都需要更新
        redisService.delete(MiaoshaUserKey.getByName,""+name);
        //更新redis中的token缓存
        //不能删除token缓存,需要更新token缓存中的User信息
        user.setPassword(toBeUpdate.getPassword());
        redisService.set(MiaoshaUserKey.token,""+token,user);

        return true;
    }




}
